﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TextAnalytics.Models;

namespace TextAnalytics
{
    public class TextSplitter
    {
        public string[] SentenceSeparators = new string[] { "? ", "! ", ". " };
        public string ParagraphSeparator = string.Format("{0}{0}", Environment.NewLine);
        public string[] WordSeparators = new string[] { "\"", ", ", " - ", " ", "(", ")", " - ", Environment.NewLine };

        #region Constructors

        private TextSplitter() { }
        public static readonly TextSplitter Default = new TextSplitter();

        #endregion

        #region Public API

        public TextSplitResultModel Split(string text)
        {
            var result = new TextSplitResultModel();

            result.Paragraphs = text.Split(new string[] { ParagraphSeparator }, StringSplitOptions.RemoveEmptyEntries)
                                    .Select(x => { return x.Trim(ParagraphSeparator.ToCharArray().First()); })
                                    .Select(x => new ParagraphModel(x.Trim()))
                                    .ToArray();
            result.ParagraphCount = result.Paragraphs.Length;
            
            foreach (var paragraph in result.Paragraphs)
            {
                var sentencesTextList = paragraph.Text.Split(SentenceSeparators, StringSplitOptions.RemoveEmptyEntries);
                foreach(var sentenceText in sentencesTextList)
                {
                    paragraph.Sentences.Add(new SentenceModel(TrimPunctuationAndWhiteSpace(sentenceText)));
                }
                result.SentenceCount += paragraph.Sentences.Count;
                int sentenceIndex = 0;
                foreach(var sentence in paragraph.Sentences)
                {
                    var sentenceModel = paragraph.Sentences[sentenceIndex];
                    var wordTextList = sentenceModel.Text.Split(WordSeparators, StringSplitOptions.RemoveEmptyEntries);

                    var wordIndex = 0;
                    foreach(var wordText in wordTextList)
                    {
                        var trimmedWordText = TrimPunctuationAndWhiteSpace(wordText);
                        if (string.IsNullOrWhiteSpace(trimmedWordText)) continue;

                        decimal res;
                        if (decimal.TryParse(trimmedWordText, out res))
                            continue;
                        DateTime date;
                        if (DateTime.TryParse(trimmedWordText, out date))
                            continue;
                        if(trimmedWordText.EndsWith("'s"))
                            trimmedWordText = trimmedWordText.Substring(0, trimmedWordText.Length-2);

                        WordModel wordModel;
                        if (!result.Words.TryGetValue(trimmedWordText, out wordModel))
                        {
                            wordModel = new WordModel(trimmedWordText);
                            result.Words.Add(trimmedWordText, wordModel);
                        }
                        var wordPosition = new WordPositionModel()
                        {
                            Paragraph = paragraph,
                            SentenceIndexInParagraph = sentenceIndex,
                            WordIndexInSentence = wordIndex
                        };
                        wordModel.Occurrences.Add(wordPosition);
                        sentenceModel.Words.Add(wordModel);
                        wordIndex++;
                    }
                    sentenceIndex++;
                }
            }

            return result;
        }

        private string TrimPunctuationAndWhiteSpace(string originalString)
        {
            int removeFromStart = 0;
            for (int i = 0; i < originalString.Length; i++)
            {
                if (char.IsPunctuation(originalString[i]) || char.IsWhiteSpace(originalString[i]))
                {
                    removeFromStart++;
                }
                else
                {
                    break;
                }
            }

            int removeFromEnd = 0;
            for (int i = originalString.Length - 1; i >= 0; i--)
            {
                if (char.IsPunctuation(originalString[i]) || char.IsWhiteSpace(originalString[i]))
                {
                    removeFromEnd++;
                }
                else
                {
                    break;
                }
            }
            if (removeFromStart == 0 && removeFromEnd == 0)
            {
                return originalString;
            }
            if (removeFromStart == originalString.Length && removeFromEnd == originalString.Length)
            {
                return string.Empty;
            }
            return originalString.Substring(removeFromStart, originalString.Length - removeFromEnd - removeFromStart);
        }

        #endregion
    }
}
